其他
VC黑防日记:DLL隐藏和逆向
>>>> 何为DLL?
何为DLL?
动态链接库英文为DLL,是Dynamic Link Library的缩写。DLL是一个包含可由多个程序,同时使用的代码和数据的库。例如,在 Windows 操作系统中,Comdlg32.dll 执行与对话框有关的常见函数。因此,每个程序都可以使用该 DLL 中包含的功能来实现“打开”对话框。这有助于避免代码重用和促进内存的有效使用。
通过使用 DLL,程序可以实现模块化,由相对独立的组件组成。例如,一个计帐程序可以按模块来销售。可以在运行时将各个模块加载到主程序中(如果安装了相应模块)。因为模块是彼此独立的,所以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。
https://encyclopedia.thefreedictionary.com/Dynamic-link+library
>>>> DLL为什么要被隐藏?
DLL为什么要被隐藏?
>>>> DLL编写
DLL编写
#include <Windows.h>
BOOL WINAPI DllMain(HMODULE hDll, DWORD dwReason, LPVOID lpReserved)
{
DisableThreadLibraryCalls(hDll);
if (dwReason == DLL_PROCESS_ATTACH)
{
//================================== OPTIONAL =========================================
MessageBoxA(0, "Message Test","Message Title", 0);
}
return 1;
}
>>>> DLL注入测试
DLL注入测试
#include <Windows.h>
void Inject(int pID, char* Path)
{
//获取进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
//申请一块内存给DLL路径
LPVOID pReturnAddress = VirtualAllocEx(hProcess, NULL, strlen(Path) + 1, MEM_COMMIT, PAGE_READWRITE);
//写入路径到上一行代码申请的内存中
WriteProcessMemory(hProcess, pReturnAddress, Path, strlen(Path) + 1, NULL);
//获取LoadLibraryA函数的地址
HMODULE hModule = LoadLibrary("KERNEL32.DLL");
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA");
//创建远程线程-并获取线程的句柄
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, pReturnAddress, 0, NULL);
//等待线程事件
WaitForSingleObject(hThread, 2000);
//防止内存泄露
CloseHandle(hThread);
CloseHandle(hProcess);
}
int main()
{
//传dll路径
const char* a = "C:\\Users\\asus\\Desktop\\C++\\FirstDll.dll";
//传入进程ID
Inject(12944, (char*)a);
return 0;
}
//获取模块句柄
HMODULE GetProcessModuleHandleByName(DWORD pid, LPCSTR ModuleName)
{
MODULEENTRY32 ModuleInfo;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (!hSnapshot)
{
return 0;
}
ZeroMemory(&ModuleInfo, sizeof(MODULEENTRY32));
ModuleInfo.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(hSnapshot, &ModuleInfo))
{
return 0;
}
do
{
if (!lstrcmpi(ModuleInfo.szModule, ModuleName))
{
CloseHandle(hSnapshot);
return ModuleInfo.hModule;
}
} while (Module32Next(hSnapshot, &ModuleInfo));
CloseHandle(hSnapshot);
return 0;
}
//获取进程id
DWORD GetProcessIDByName(const char* pName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, pName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
//printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
}
CloseHandle(hSnapshot);
return 0;
}
#include <Windows.h>
#include <stdio.h>
#include "tlhelp32.h"
void Inject(int pID, char* Path)
{
//获取进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
//申请一块内存给DLL路径
LPVOID pReturnAddress = VirtualAllocEx(hProcess, NULL, strlen(Path) + 1, MEM_COMMIT, PAGE_READWRITE);
//写入路径到上一行代码申请的内存中
WriteProcessMemory(hProcess, pReturnAddress, Path, strlen(Path) + 1, NULL);
//获取LoadLibraryA函数的地址
HMODULE hModule = LoadLibrary("KERNEL32.DLL");
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA");
//创建远程线程-并获取线程的句柄
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, pReturnAddress, 0, NULL);
//等待线程事件
WaitForSingleObject(hThread, 2000);
//防止内存泄露
CloseHandle(hThread);
CloseHandle(hProcess);
}
HMODULE GetProcessModuleHandleByName(DWORD pid, LPCSTR ModuleName)
{
MODULEENTRY32 ModuleInfo;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (!hSnapshot)
{
return 0;
}
ZeroMemory(&ModuleInfo, sizeof(MODULEENTRY32));
ModuleInfo.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(hSnapshot, &ModuleInfo))
{
return 0;
}
do
{
if (!lstrcmpi(ModuleInfo.szModule, ModuleName))
{
CloseHandle(hSnapshot);
return ModuleInfo.hModule;
}
} while (Module32Next(hSnapshot, &ModuleInfo));
CloseHandle(hSnapshot);
return 0;
}
DWORD GetProcessIDByName(const char* pName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, pName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
//printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
}
CloseHandle(hSnapshot);
return 0;
}
void UnInject(int pID, char* Path)
{
//获取进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
LPVOID pReturnAddress = GetProcessModuleHandleByName(GetProcessIDByName("代码注入器.exe"), "mydll.dll");
//获取LoadLibraryA函数的地址
HMODULE hModule = LoadLibrary("KERNEL32.DLL");
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
//创建远程线程-并获取线程的句柄
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, pReturnAddress, 0, NULL);
//等待线程事件
WaitForSingleObject(hThread, 2000);
//防止内存泄露
CloseHandle(hThread);
CloseHandle(hProcess);
}
int main()
{
const char* a = "C:\\Users\\86186\\Desktop\\mydll.dll";
UnInject(GetProcessIDByName("代码注入器.exe"), (char*)a);
getchar();
return 0;
}
1. 判断DLL句柄是否有效,有效就说明该DLL存在于进程中
2. 递减模块的引用计数,且判断是否为0
3. 调用模块的DllMain函数响应 DLL_PROCESS_DETACH消息
4. 从进程空间撤销对DLL的内存映射
The ZwUnmapViewOfSection routine unmaps a view of a section from the virtual address space of a subject process.
DWORD a = GetProcAddress(LoadLibrary("ntdll.dll"), "ZwUnmapViewOfSection");
DWORD dwOldProtect;
VirtualProtectEx(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIDByName("代码注入器.exe")),
addrfun,
6,
PAGE_EXECUTE_READWRITE,
&dwOldProtect);
BYTE shellcode[] = { 0xc2, 0x08 , 0x00 , 0x90 , 0x90 };
WriteProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIDByName("代码注入器.exe")), addrfun, shellcode, 5, NULL);
后续:干掉吾爱破解OD这类工具DLL的检测
欲知后事如何,且听我下回分晓~
#include <Windows.h>
#include <stdio.h>
#include "tlhelp32.h"
void Inject(int pID, char* Path)
{
//获取进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
//申请一块内存给DLL路径
LPVOID pReturnAddress = VirtualAllocEx(hProcess, NULL, strlen(Path) + 1, MEM_COMMIT, PAGE_READWRITE);
//写入路径到上一行代码申请的内存中
WriteProcessMemory(hProcess, pReturnAddress, Path, strlen(Path) + 1, NULL);
//获取LoadLibraryA函数的地址
HMODULE hModule = LoadLibrary("KERNEL32.DLL");
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA");
//创建远程线程-并获取线程的句柄
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, pReturnAddress, 0, NULL);
//等待线程事件
WaitForSingleObject(hThread, 2000);
//防止内存泄露
CloseHandle(hThread);
CloseHandle(hProcess);
}
HMODULE GetProcessModuleHandleByName(DWORD pid, LPCSTR ModuleName)
{
MODULEENTRY32 ModuleInfo;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (!hSnapshot)
{
return 0;
}
ZeroMemory(&ModuleInfo, sizeof(MODULEENTRY32));
ModuleInfo.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(hSnapshot, &ModuleInfo))
{
return 0;
}
do
{
if (!lstrcmpi(ModuleInfo.szModule, ModuleName))
{
CloseHandle(hSnapshot);
return ModuleInfo.hModule;
}
} while (Module32Next(hSnapshot, &ModuleInfo));
CloseHandle(hSnapshot);
return 0;
}
DWORD GetProcessIDByName(const char* pName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) {
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
if (strcmp(pe.szExeFile, pName) == 0) {
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
//printf("%-6d %s\n", pe.th32ProcessID, pe.szExeFile);
}
CloseHandle(hSnapshot);
return 0;
}
void UnInject(int pID, char* Path)
{
//获取进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
//WriteProcessMemory("")
LPVOID pReturnAddress = GetProcessModuleHandleByName(GetProcessIDByName("代码注入器.exe"), "mydll.dll");
//获取LoadLibraryA函数的地址
HMODULE hModule = LoadLibrary("KERNEL32.DLL");
LPTHREAD_START_ROUTINE lpStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
//创建远程线程-并获取线程的句柄
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, pReturnAddress, 0, NULL);
//等待线程事件
WaitForSingleObject(hThread, 2000);
//防止内存泄露
CloseHandle(hThread);
CloseHandle(hProcess);
}
int main()
{
const char* a = "C:\\Users\\86186\\Desktop\\mydll.dll";
HANDLE hToken = NULL;
//打开当前进程的访问令牌
int hRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken);
if (hRet)
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
//取得描述权限的LUID
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//调整访问令牌的权限
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
CloseHandle(hToken);
}
//定位函数地址
DWORD addrfun = GetProcAddress(LoadLibrary("ntdll.dll"), "ZwUnmapViewOfSection");
printf("%x \n\n", addrfun);
DWORD dwOldProtect;
//修改内存属性
VirtualProtectEx(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIDByName("代码注入器.exe")), addrfun, 6, PAGE_EXECUTE_READWRITE, &dwOldProtect);
//阉割函数
BYTE shellcode[] = { 0xc2, 0x08 , 0x00 , 0x90 , 0x90 };
WriteProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIDByName("代码注入器.exe")), addrfun, shellcode, 5, NULL);
//调用FreeLibrary实现卸载
UnInject(GetProcessIDByName("代码注入器.exe"), (char*)a);
//还原原函数
//B8 27 00 00 00
BYTE Oldcode[] = { 0xB8, 0x27 , 0x00 , 0x00 , 0x00 };
WriteProcessMemory(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIDByName("代码注入器.exe")), addrfun, Oldcode, 5, NULL);
getchar();
return 0;
}
看雪ID:小迪xiaodi
https://bbs.pediy.com/user-680946.htm
推荐文章++++
好书推荐